# coding: utf-8
# @Time    : 2023/3/6 18:51
# @Author  : gongshuangxi
# @Email   : sxgong@topdatasec.com

import os
import re
import sys
import json
from flask import request
from macro import recode

try:
    # python2
    reload(sys)
    sys.setdefaultencoding('utf-8')
except:
    # python3
    pass

# 根据错误码和错误信息返回字典
def return_dict(code, msg, owner=None):
    re_dict = dict()
    re_dict['recode'] = code
    re_dict['remsg'] = msg
    if owner is not None:
        re_dict['owner'] = owner
    return re_dict


def result_dict(code, msg_dict, owner=None):
    re_dict = {'recode': -1000000, 'remsg':'未知错误'}
    if not isinstance(code, int) or code not in msg_dict.keys():
        return return_dict

    re_dict['recode'] = code
    re_dict['remsg'] = msg_dict[code]
    if owner is not None:
        re_dict['owner'] = owner
    return re_dict


def check_dict_keys_plus(conf_data, check_list, loghandle):
    if not isinstance(conf_data, dict):
        return False
    keys_list = conf_data.keys()
    re_list = list(set(check_list).difference(set(keys_list)))
    if len(re_list) != 0:
        loghandle.error("conf dict keys must include these %s" % check_list)
        return False, re_list
    return True, re_list


def check_input_data(pattern, objstr, loghandle, need_decode=False):
    try:
        if (not not isinstance(pattern, str) and not isinstance(pattern, str)) or len(pattern) == 0:
            return False
        try:
            # python2
            if not isinstance(objstr, unicode) and not isinstance(objstr, str):
                return False
        except:
            # python3
            if not isinstance(objstr, str):
                return False
        if need_decode:
            objstr = objstr.decode('utf-8', 'ignore')
        if re.match(pattern, objstr) is None:
            # loghandle.error("invalid objstr: %s" % objstr)
            return False
        return True
    except Exception as e:
        loghandle.error("check input data: %s with pattern: %s except: %s" % (pattern, objstr, e))
        return False


def check_input_uuid(objstr, loghandle):
    return check_input_data("\w{8}(-\w{4}){3}-(\w{12})$", objstr, loghandle)


# 中英文字符数字及_，检查输入名称
def check_input_name(objstr, loghandle):
    return check_input_data(u"^[\u4e00-\u9fa5_a-zA-Z0-9]+$", objstr, loghandle, True)


# 中英文字符、数字、下划线、空白字符（空格，制表符，换行等）、中文标点（。；，：“”（）、？《》），检查输入描述信息
def check_input_desc(objstr, loghandle):
    return check_input_data(u"^[\u3002\uff1b\uff0c\uff1a\u201c\u201d\uff08\uff09\u3001\uff1f\u300a\u300b\u4e00-\u9fa5_a-zA-Z0-9\s]+$", objstr, loghandle, True)


def check_get_token(loghandle):
    # 页面请求
    try:
        # result = CheckUser.TdsCheckUser(request)
        # if result != 0:
        #     loghandle.error(
        #         "auth filed| result: %d, request: %s, remote_addr: %s" % (result, request, request.remote_addr))
        #     return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
        # 取出tds_token值
        old_token = str(request.args.get('tds_token'))
        if not isinstance(old_token, str) or len(old_token) == 0:
            loghandle.error("tds_token invalid, get args: %s" % request.args)
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
        # 从sds_token中获取真正的owner值
        owner_dict = dict()

        sds_token_list = old_token.split(',')
        if len(sds_token_list) < 4:
            loghandle.error("get real owner faied from tds_token: %s" % old_token)
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

        if not isinstance(sds_token_list[1], str) or \
                len(sds_token_list[1]) not in range(1, 37):
            loghandle.error("real owner type or length invlid, owner: %s" % sds_token_list[1])
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

        # 增加格式校验
        if not check_input_uuid(sds_token_list[1], loghandle):
            loghandle.error("invalid owner uuid format.")
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

        if not isinstance(sds_token_list[3], str) or \
                len(sds_token_list[3]) not in range(1, 37):
            loghandle.error("real tenant type or length invlid, tenant: %s" % sds_token_list[3])
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

        # 返回真正的owner
        owner_dict['owner'] = sds_token_list[1]
        owner_dict['role'] = sds_token_list[2]
        owner_dict['tenant'] = sds_token_list[3].replace("\'", "\\'")
    except Exception as e:
        loghandle.error("get real owner exception %s" % e)
        return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
    return True, owner_dict



# 检查POST和DELETE提交的数据合法性
def check_common_data(need_key_list, loghandle, check_user=True):
    msg_dict = recode.COMMON_ERR_MSG_DICT
    data = request.get_data()
    # loghandle.debug("in check_common_data| request.get_data(): %s" % data)
    try:
        jl_data = json.loads(data, strict=False)
        # loghandle.debug("post dict data : %s" % jl_data)
    except Exception as e:
        loghandle.error("trans post data to dict exception: %s" % e)
        return False, result_dict(recode.COMMON_INPUT_ERROR, msg_dict)

    # 校验请求合法性
    # 脱敏引擎使用token, 页面请求使用tds_token
    if check_user is True:
        try:
            # # 页面请求
            # result = CheckUser.TdsCheckUser(request)
            # if result !=0:
            #     loghandle.error("auth filed| result: %d, request: %s, remote_addr: %s" % (result, request, request.remote_addr))
            #     return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
            # 取出sds_token值
            old_token = str(jl_data.get('tds_token'))
            if not isinstance(old_token, str) or len(old_token) == 0:
                loghandle.error("tds_token invalid, post data: %s" % data)
                return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
            # 从sds_token中获取真正的owner值
            sds_token_list = old_token.split(',')
            if len(sds_token_list) < 4:
                loghandle.error("get real owner faied from tds_token: %s" % old_token)
                return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

            if not isinstance(sds_token_list[1], str) or \
                len(sds_token_list[1]) not in range(1, 37):
                loghandle.error("real owner type or length invlid, owner: %s" % sds_token_list[1])
                return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
            # 增加格式校验
            if not check_input_uuid(sds_token_list[1], loghandle):
                loghandle.error("invalid owner uuid format.")
                return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
            if not isinstance(sds_token_list[3], str) or \
                    len(sds_token_list[3]) not in range(1, 37):
                loghandle.error("real tenant type or length invlid, tenant: %s" % sds_token_list[3])
                return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

            # 返回真正的owner
            jl_data['owner'] = sds_token_list[1]
            jl_data['role'] = sds_token_list[2]
            jl_data['tenant'] = sds_token_list[3].replace("\'", "\\'")
        except Exception as e:
            loghandle.error("get real owner exception %s" % e)
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
    else:
        # 暂时不校验引擎发起请求的token信息
        pass

    # 检查必须的参数
    result, re_list = check_dict_keys_plus(jl_data, need_key_list, loghandle)
    if not result:
        loghandle.error("need these para: %s" % re_list)
        return False, return_dict(recode.COMMON_INPUT_ERROR, "缺少必须的输入参数: %s" % ",".join(re_list))

    return True, jl_data


# 校验token合法性
def check_form_token(loghandle):
    # 页面请求
    try:
        # result = CheckUser.TdsCheckUser(request, formdata=True)
        result = 0
        if result != 0:
            loghandle.error("auth filed| result: %d, request: %s, remote_addr: %s" % (result, request, request.remote_addr))
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
        # 取出sds_token值
        old_token = str(request.form.get('tds_token'))
        if not isinstance(old_token, str) or len(old_token) == 0:
            loghandle.error("tds_token invalid, get request.form: %s" % request.form)
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
        # 从sds_token中获取真正的owner值
        owner_dict = dict()
        try:
            sds_token_list = old_token.encode('utf-8').split(',')
        except Exception as e:
            loghandle.error("trans sds_token to str except: %s " % str(e))
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

        if len(sds_token_list) < 4:
            loghandle.error("get real owner faied from sds_token: %s" % old_token)
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

        # loghandle.info("type(sds_token_list[1]): %s" % type(sds_token_list[1]))
        if not isinstance(sds_token_list[1], str) or \
                len(sds_token_list[1]) not in range(1, 37):
            loghandle.error("real owner type or length invlid, owner: %s" % sds_token_list[1])
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
        # 增加格式校验
        if not check_input_uuid(sds_token_list[1], loghandle):
            loghandle.error("invalid owner uuid format.")
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
        if not isinstance(sds_token_list[3], str) or \
                len(sds_token_list[3]) not in range(1, 37):
            loghandle.error("real tenant type or length invlid, tenant: %s" % sds_token_list[3])
            return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")

        # 返回真正的owner
        owner_dict['owner'] = sds_token_list[1]
        owner_dict['tenant'] = sds_token_list[3].replace("\'", "\\'")
    except Exception as e:
        loghandle.error("get real owner exception %s" % e)
        return False, return_dict(recode.COMMON_AUTH_FAILED, "认证失败")
    return True, owner_dict

